package com.spzx.channel.service.impl;

import com.alibaba.fastjson.JSON;
import com.spzx.channel.domain.vo.ItemVo;
import com.spzx.channel.service.ItemService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.domain.R;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.domain.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class ItemServiceImpl implements ItemService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RemoteProductService remoteProductService;


    @Override
    public ItemVo itemCache(Long skuId) {
        long start = System.currentTimeMillis();
        //初步使用缓存
        ItemVo itemVo = (ItemVo) redisTemplate.opsForValue().get("itemvo:" + skuId);

        //缓存没有数据，就查数据库

        if (itemVo == null) {
            //让一个线程拿到锁去查数据库并把数据库放到缓存，其他线程等待自旋等待
            //生成锁的uuid去掉-
            String lockUUID = UUID.randomUUID().toString().replace("-", "");
            redisTemplate.opsForValue().setIfAbsent("item:querylock", lockUUID, 5, TimeUnit.SECONDS);

            itemVo = item(skuId);

            redisTemplate.opsForValue().set("itemvo:" + skuId, itemVo);
            //不使用lua脚本进行这个操作
            // 使用Lua脚本释放锁，保证原子性
            String script =
                    "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                            "    return redis.call('del', KEYS[1]) " +
                            "else " +
                            "    return 0 " +
                            "end";
            redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),
                    Collections.singletonList("item:querylock"), lockUUID);
        }else {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            itemCache(skuId);
        }

        long end = System.currentTimeMillis();
        System.out.println("使用缓存优化" + (end - start));
        return itemVo;

    }


    @Override
    public ItemVo item(Long skuId) {
        long start = System.currentTimeMillis();

        ItemVo itemVo = new ItemVo();

        R<ProductSku> productSkuR = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
        Long productId = productSkuR.getData().getProductId();
        itemVo.setProductSku(productSkuR.getData());

        R<Product> productR = remoteProductService.getProduct(productId, SecurityConstants.INNER);
        itemVo.setProduct(productR.getData());


        R<ProductDetails> productDetailsR = remoteProductService.getProductDetails(productId, SecurityConstants.INNER);
        String[] urlList = productDetailsR.getData().getImageUrls().split(",");
        itemVo.setDetailsimagesUrlList(Arrays.stream(urlList).toList());

        itemVo.setSliderUrlList(Arrays.stream(productR.getData().getSliderUrls().split(",")).toList());

        R<SkuPrice> skuPriceR = remoteProductService.getSkuPrice(skuId, SecurityConstants.INNER);
        itemVo.setSkuPrice(skuPriceR.getData());

//        R<Map<String, Long>> skuSpecValueR = remoteProductService.getSkuSpecValue(skuId, SecurityConstants.INNER);
//        itemVo.setSkuSpecValueMap(skuSpecValueR.getData());

        itemVo.setSpecValueList(JSON.parseArray(productR.getData().getSpecValue()));

        R<Map<String, Object>> skuSpecMapR = remoteProductService.getSkuSpecValueMap(productId, SecurityConstants.INNER);
        itemVo.setSkuSpecValueMap(skuSpecMapR.getData());

        R<SkuStockVo> skuStockR = remoteProductService.getSkuStock(skuId, SecurityConstants.INNER);
        itemVo.setSkuStockVo(skuStockR.getData());

        //在此自行整合specMap

        long end = System.currentTimeMillis();

        System.out.println("不使用缓存使用的时间" + (end - start) + "ms");
        return itemVo;
    }


}
